home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Taifun / Taifun 007 (1987-02-15)(Ossowski, Stefan)(DE)(PD).zip / Taifun 007 (1987-02-15)(Ossowski, Stefan)(DE)(PD).adf / C Compiler / peepgen.c < prev    next >
C/C++ Source or Header  |  1987-03-04  |  11KB  |  364 lines

  1. #include        <stdio.h>
  2. #include        "c.h"
  3. #include        "expr.h"
  4. #include        "gen.h"
  5. #include        "cglbdec.h"
  6.  
  7. /*
  8.  *    68000 C compiler
  9.  *
  10.  *    Copyright 1984, 1985, 1986 Matthew Brandt.
  11.  *    all commercial rights reserved.
  12.  *
  13.  *    This compiler is intended as an instructive tool for personal use. Any
  14.  *    use for profit without the written consent of the author is prohibited.
  15.  *
  16.  *    This compiler may be distributed freely for non-commercial use as long
  17.  *    as this notice stays intact. Please forward any enhancements or questions
  18.  *    to:
  19.  *
  20.  *        Matthew Brandt
  21.  *        Box 920337
  22.  *        Norcross, Ga 30092
  23.  */
  24.  
  25. struct ocode    *peep_head = 0,
  26.                 *peep_tail = 0;
  27.  
  28. struct amode    *copy_addr(ap)
  29. /*
  30.  *      copy an address mode structure (these things dont last).
  31.  */
  32. struct amode    *ap;
  33. {       struct amode    *newap;
  34.         if( ap == 0 )
  35.                 return 0;
  36.         newap = xalloc(sizeof(struct amode));
  37.         newap->mode = ap->mode;
  38.         newap->preg = ap->preg;
  39.         newap->sreg = ap->sreg;
  40.         newap->tempflag = ap->tempflag;
  41.         newap->deep = ap->deep;
  42.         newap->offset = ap->offset;
  43.         return newap;
  44. }
  45.  
  46. gen_code(op,len,ap1,ap2)
  47. /*
  48.  *      generate a code sequence into the peep list.
  49.  */
  50. enum e_op op;
  51. int             len;
  52. struct amode    *ap1, *ap2;
  53. {       struct ocode    *new;
  54.         new = xalloc(sizeof(struct ocode));
  55.         new->opcode = op;
  56.         new->length = len;
  57.         new->oper1 = copy_addr(ap1);
  58.         new->oper2 = copy_addr(ap2);
  59.         add_peep(new);
  60. }
  61.  
  62. add_peep(new)
  63. /*
  64.  *      add the ocoderuction pointed to by new to the peep list.
  65.  */
  66. struct ocode    *new;
  67. {       if( peep_head == 0 )
  68.                 {
  69.                 peep_head = peep_tail = new;
  70.                 new->fwd = 0;
  71.                 new->back = 0;
  72.                 }
  73.         else
  74.                 {
  75.                 new->fwd = 0;
  76.                 new->back = peep_tail;
  77.                 peep_tail->fwd = new;
  78.                 peep_tail = new;
  79.                 }
  80. }
  81.  
  82. gen_label(labno)
  83. /*
  84.  *      add a compiler generated label to the peep list.
  85.  */
  86. int     labno;
  87. {       struct ocode    *new;
  88.         new = xalloc(sizeof(struct ocode));
  89.         new->opcode = op_label;
  90.         new->oper1 = labno;
  91.         add_peep(new);
  92. }
  93.  
  94. flush_peep()
  95. /*
  96.  *      output all code and labels in the peep list.
  97.  */
  98. {       opt3();         /* do the peephole optimizations */
  99.         while( peep_head != 0 )
  100.                 {
  101.                 if( peep_head->opcode == op_label )
  102.                         put_label(peep_head->oper1);
  103.                 else
  104.                         put_ocode(peep_head);
  105.                 peep_head = peep_head->fwd;
  106.                 }
  107. }
  108.  
  109. put_ocode(p)
  110. /*
  111.  *      output the instruction passed.
  112.  */
  113. struct ocode    *p;
  114. {       put_code(p->opcode,p->length,p->oper1,p->oper2);
  115. }
  116.  
  117. peep_move(ip)
  118. /*
  119.  *      peephole optimization for move instructions.
  120.  *      makes quick immediates when possible.
  121.  *      changes move #0,d to clr d.
  122.  *      changes long moves to address registers to short when
  123.  *              possible.
  124.  *      changes move immediate to stack to pea.
  125.  */
  126. struct ocode    *ip;
  127. {       struct enode    *ep;
  128.         if( ip->oper1->mode != am_immed )
  129.                 return;
  130.         ep = ip->oper1->offset;
  131.         if( ep->nodetype != en_icon )
  132.                 return;
  133.         if( ip->oper2->mode == am_areg )
  134.                 {
  135.                 if( -32768 <= ep->v.i && ep->v.i <= 32768 )
  136.                         ip->length = 2;
  137.                 }
  138.         else if( ip->oper2->mode == am_dreg )
  139.                 {
  140.                 if( -128 <= ep->v.i && ep->v.i <= 127 )
  141.                         {
  142.                         ip->opcode = op_moveq;
  143.                         ip->length = 0;
  144.                         }
  145.                 }
  146.         else
  147.                 {
  148.                 if( ep->v.i == 0 )
  149.                         {
  150.                         ip->opcode = op_clr;
  151.                         ip->oper1 = ip->oper2;
  152.                         ip->oper2 = 0;
  153.                         }
  154.                 else if( ip->oper2->mode == am_adec && ip->oper2->preg == 7 )
  155.                         {
  156.                         ip->opcode = op_pea;
  157.                         ip->length = 0;
  158.                         ip->oper1->mode = am_direct;
  159.                         ip->oper2 = 0;
  160.                         }
  161.                 }
  162. }
  163.  
  164. int     equal_address(ap1,ap2)
  165. /*
  166.  *      compare two address nodes and return true if they are
  167.  *      equivalent.
  168.  */
  169. struct amode    *ap1, *ap2;
  170. {       if( ap1 == 0 || ap2 == 0 )
  171.                 return 0;
  172.         if( ap1->mode != ap2->mode )
  173.                 return 0;
  174.         switch( ap1->mode )
  175.                 {
  176.                 case am_areg:   case am_dreg:
  177.                 case am_ainc:   case am_adec:
  178.                         return ap1->preg == ap2->preg;
  179.                 }
  180.         return 0;
  181. }
  182.  
  183. peep_add(ip)
  184. /*
  185.  *      peephole optimization for add instructions.
  186.  *      makes quick immediates out of small constants.
  187.  */
  188. struct ocode    *ip;
  189. {       struct enode    *ep;
  190.         if( ip->oper1->mode != am_immed )
  191.                 return;
  192.         ep = ip->oper1->offset;
  193.         if( ip->oper2->mode != am_areg )
  194.                 ip->opcode = op_addi;
  195.         else
  196.                 {
  197.                 if( isshort(ep) )
  198.                         ip->length = 2;
  199.                 }
  200.         if( ep->nodetype != en_icon )
  201.                 return;
  202.         if( 1 <= ep->v.i && ep->v.i <= 8 )
  203.                 ip->opcode = op_addq;
  204.         else if( -8 <= ep->v.i && ep->v.i <= -1 )
  205.                 {
  206.                 ip->opcode = op_subq;
  207.                 ep->v.i = -ep->v.i;
  208.                 }
  209. }
  210.  
  211. peep_sub(ip)
  212. /*
  213.  *      peephole optimization for subtract instructions.
  214.  *      makes quick immediates out of small constants.
  215.  */
  216. struct ocode    *ip;
  217. {       struct enode    *ep;
  218.         if( ip->oper1->mode != am_immed )
  219.                 return;
  220.         ep = ip->oper1->offset;
  221.         if( ip->oper2->mode != am_areg )
  222.                 ip->opcode = op_subi;
  223.         else
  224.                 {
  225.                 if( isshort(ep) )
  226.                         ip->length = 2;
  227.                 }
  228.         if( ep->nodetype != en_icon )
  229.                 return;
  230.         if( 1 <= ep->v.i && ep->v.i <= 8 )
  231.                 ip->opcode = op_subq;
  232.         else if( -8 <= ep->v.i && ep->v.i <= -1 )
  233.                 {
  234.                 ip->opcode = op_addq;
  235.                 ep->v.i = -ep->v.i;
  236.                 }
  237. }
  238.  
  239. int     peep_cmp(ip)
  240. /*
  241.  *      peephole optimization for compare instructions.
  242.  *      changes compare #0 to tst and if previous instruction
  243.  *      should have set the condition codes properly delete.
  244.  *      return value is true if instruction was deleted.
  245.  */
  246. struct ocode    *ip;
  247. {       struct ocode    *prev;
  248.         struct enode    *ep;
  249.         if( ip->oper1->mode != am_immed )
  250.                 return;
  251.         ep = ip->oper1->offset;
  252.         if( ip->oper2->mode == am_areg )
  253.                 {
  254.                 if( isshort(ep) )
  255.                         ip->length = 2;
  256.                 return;
  257.                 }
  258.         ip->opcode = op_cmpi;
  259.         if( ep->nodetype != en_icon || ep->v.i != 0 )
  260.                 return;
  261.         ip->oper1 = ip->oper2;
  262.         ip->oper2 = 0;
  263.         ip->opcode = op_tst;
  264.         prev = ip->back;
  265.         if( prev == 0 )
  266.                 return;
  267.         if( (((prev->opcode == op_move || prev->opcode == op_moveq) &&
  268.                 equal_address(prev->oper1,ip->oper1)) &&
  269.                 prev->oper2->mode != am_areg) ||
  270.                 (prev->opcode != op_label &&
  271.                 equal_address(prev->oper2,ip->oper1)) )
  272.                 {
  273.                 prev->fwd = ip->fwd;
  274.                 if( prev->fwd != 0 )
  275.                         prev->fwd->back = prev;
  276.                 }
  277. }
  278.  
  279. peep_muldiv(ip,op)
  280. /*
  281.  *      changes multiplies and divides by convienient values
  282.  *      to shift operations. op should be either op_asl or
  283.  *      op_asr (for divide).
  284.  */
  285. struct ocode    *ip;
  286. enum e_op op;
  287. {       int     shcnt;
  288.         if( ip->oper1->mode != am_immed )
  289.                 return;
  290.         if( ip->oper1->offset->nodetype != en_icon )
  291.                 return;
  292.         shcnt = ip->oper1->offset->v.i;
  293. /*      vax c doesn't do this type of switch well       */
  294.         if( shcnt == 2) shcnt = 1;
  295.         else if( shcnt == 4) shcnt = 2;
  296.         else if( shcnt == 8) shcnt = 3;
  297.         else if( shcnt == 16) shcnt = 4;
  298.         else if( shcnt == 32) shcnt = 5;
  299.         else if( shcnt == 64) shcnt = 6;
  300.         else if( shcnt == 128) shcnt = 7;
  301.         else if( shcnt == 256) shcnt = 8;
  302.         else if( shcnt == 512) shcnt = 9;
  303.         else if( shcnt == 1024) shcnt = 10;
  304.         else if( shcnt == 2048) shcnt = 11;
  305.         else if( shcnt == 4096) shcnt = 12;
  306.         else if( shcnt == 8192) shcnt = 13;
  307.         else if( shcnt == 16384) shcnt = 14;
  308.         else return;
  309.         ip->oper1->offset->v.i = shcnt;
  310.         ip->opcode = op;
  311.         ip->length = 4;
  312. }
  313.  
  314. peep_uctran(ip)
  315. /*
  316.  *      peephole optimization for unconditional transfers.
  317.  *      deletes instructions which have no path.
  318.  *      applies to bra, jmp, and rts instructions.
  319.  */
  320. struct ocode    *ip;
  321. {       while( ip->fwd != 0 && ip->fwd->opcode != op_label )
  322.                 {
  323.                 ip->fwd = ip->fwd->fwd;
  324.                 if( ip->fwd != 0 )
  325.                         ip->fwd->back = ip;
  326.                 }
  327. }
  328.  
  329. opt3()
  330. /*
  331.  *      peephole optimizer. This routine calls the instruction
  332.  *      specific optimization routines above for each instruction
  333.  *      in the peep list.
  334.  */
  335. {       struct ocode    *ip;
  336.         ip = peep_head;
  337.         while( ip != 0 )
  338.                 {
  339.                 switch( ip->opcode )
  340.                         {
  341.                         case op_move:
  342.                                 peep_move(ip);
  343.                                 break;
  344.                         case op_add:
  345.                                 peep_add(ip);
  346.                                 break;
  347.                         case op_sub:
  348.                                 peep_sub(ip);
  349.                                 break;
  350.                         case op_cmp:
  351.                                 peep_cmp(ip);
  352.                                 break;
  353.                         case op_muls:
  354.                                 peep_muldiv(ip,op_asl);
  355.                                 break;
  356.                         case op_bra:
  357.                         case op_jmp:
  358.                         case op_rts:
  359.                                 peep_uctran(ip);
  360.                         }
  361.                 ip = ip->fwd;
  362.                 }
  363. }
  364.